#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Lee
# @File    : dhy_anti_interference_endurance_view.py
# @Time    : 2024/1/23 11:38
import time
import numpy as np
from util.common_calc import *
from PyQt5 import QtCore, QtWidgets
from util.global_config import global_config
from PyQt5.QtWidgets import QWidget, QMessageBox
from util.utm_transformer import transformer_to_utm
from views.alert_messagebox_view import show_message_box
from util.get_localization_points import GetLocalizationPoints
from views.dhy_connect_row_matplotlib_view import ConnectRowMplWidget
from views.resource_view.anti_interference_endurance_view import Ui_DHYAntiInterferenceEnduranceView

# 抗扰续航时间
# 所有前端展示数据为经纬度
# 所有后台计算数据需要转换为UTM坐标

# AB线
lat_ab_a, lon_ab_a = 35.62227366290924, 119.47524265975274
lat_ab_b, lon_ab_b = 35.621845907241564, 119.4727659321641

# A+线
lat_a_plus, lon_a_plus = 35.62228255125184, 119.47529142702435


class DHYAntiInterferenceEnduranceView(QWidget, Ui_DHYAntiInterferenceEnduranceView):
    def __init__(self, parent=None):
        super(DHYAntiInterferenceEnduranceView, self).__init__(parent)
        self.setupUi(self)

        # 监听测试类别
        self.ABLine.clicked.connect(lambda: self.set_test_type("ab_line"))
        self.APlusLine.clicked.connect(lambda: self.set_test_type("a_plus_line"))

        # 添加matplotlib视图
        matplotlib_widget = ConnectRowMplWidget(self)
        self.matplotlib_layout.addWidget(matplotlib_widget)
        self.matplotlib_view = matplotlib_widget.qCanvas

        self.csv_file_path = ""
        self.matplotlib_view_points = None

        self.load_data_btn.clicked.connect(self.select_csv_file)
        self.redraw_line_btn.clicked.connect(self.draw_base_line)
        self.start_test_btn.clicked.connect(self.start_anti_interference_endurance_test)

        self.set_test_type("ab_line")

    # 修改测试类别，AB线时角度模块置灰；A+线时B点坐标模块置灰
    def set_test_type(self, test_type):
        if test_type == "ab_line":
            self.ABLine.setChecked(True)
            self.angle_group.setEnabled(False)
            self.point_b_group.setEnabled(True)
        elif test_type == "a_plus_line":
            self.APlusLine.setChecked(True)
            self.angle_group.setEnabled(True)
            self.point_b_group.setEnabled(False)

        if self.csv_file_path:
            self.draw_base_line()

    @QtCore.pyqtSlot()
    def select_csv_file(self):
        options = QtWidgets.QFileDialog.Options()
        options |= QtWidgets.QFileDialog.DontUseNativeDialog
        self.csv_file_path, _ = QtWidgets.QFileDialog.getOpenFileName(None, "QFileDialog.getOpenFileName()", "",
                                                                      "CSV Files (*.csv)", options=options)
        self.load_trajectory_points_data()

    def load_trajectory_points_data(self):
        self.matplotlib_view.load_data_with_csv_file_path(self.csv_file_path, is_anti_interference_endurance=True)
        if self.csv_file_path:
            self.matplotlib_view_points = np.loadtxt(self.csv_file_path, delimiter=',')

            # _a_x, _a_y = transformer_to_utm(lat_ab_a, lon_ab_a)
            # _b_x, _b_y = transformer_to_utm(lat_ab_b, lon_ab_b)
            self.point_a_x_text.setText(str(round(lat_ab_a, 8)))
            self.point_a_y_text.setText(str(round(lon_ab_a, 8)))
            self.point_b_x_text.setText(str(round(lat_ab_b, 8)))
            self.point_b_y_text.setText(str(round(lon_ab_b, 8)))
            if self.matplotlib_view_points.shape[-1] == 8:
                self.angle_text.setText(str(round(self.matplotlib_view_points[0][4], 2)))
            self.draw_base_line()

    def get_clicked_index(self, index):
        _clicked_point_time = int(self.matplotlib_view_points[index][0])
        _format_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(_clicked_point_time))
        _title = "设置服务关闭时间"
        _text = "将：【{}】【{}】设置为服务关闭时间？设置后将从下一秒开始计算抗扰续航时间".format(_format_time, _clicked_point_time)
        _btn_text_list = ["确定", "取消"]
        clicked_btn = show_message_box(_title, _text, _btn_text_list)
        if clicked_btn == "确定":
            _x, _y = 0, 0
            if self.matplotlib_view_points.shape[-1] == 8:
                _x, _y = transformer_to_utm(*self.matplotlib_view_points[index][-3:-1])
            else:
                _x, _y = transformer_to_utm(*self.matplotlib_view_points[index][-2:])
            self.matplotlib_view.update_line([[_x, _x], [_y - 4,  _y + 2]], "left_line")
            self.close_service_text.setText(str(_clicked_point_time))

    @QtCore.pyqtSlot()
    def draw_base_line(self):
        _point_a = [float(self.point_a_x_text.text()), float(self.point_a_y_text.text())]
        _utm_a_x, _utm_a_y = transformer_to_utm(*_point_a)
        if self.ABLine.isChecked():  # 测试类型为AB线
            _point_b = [float(self.point_b_x_text.text()), float(self.point_b_y_text.text())]
            _utm_b_x, _utm_b_y = transformer_to_utm(*_point_b)
            self.matplotlib_view.update_line([[_utm_a_x, _utm_b_x],
                                              [_utm_a_y, _utm_b_y]], "ab_line")
        elif self.APlusLine.isChecked():
            _angle = float(self.angle_text.text()) + float(self.angle_dis_text.text()) * math.pi / 180
            # 判断起始点大小，确认行驶方向
            _start_point, _end_point = tuple(), tuple()
            if self.matplotlib_view_points.shape[-1] == 8:
                _start_point = transformer_to_utm(*self.matplotlib_view_points[0][-3:-1])
                _end_point = transformer_to_utm(*self.matplotlib_view_points[-1][-3:-1])
            else:
                _start_point = transformer_to_utm(*self.matplotlib_view_points[0][-2:])
                _end_point = transformer_to_utm(*self.matplotlib_view_points[-1][-2:])
            _point_b = get_virtual_point([_utm_a_x, _utm_a_y], _start_point, _end_point, _angle)
            self.matplotlib_view.update_line([[_utm_a_x, _point_b[0]],
                                              [_utm_a_y, _point_b[1]]], "ab_line")

    @QtCore.pyqtSlot()
    def start_anti_interference_endurance_test(self):
        if float(self.close_service_text.text()) < 1705000000:
            QMessageBox(QMessageBox.Warning, "警告", "测试前请先设置服务关闭时间！")
            return
        # 计算轨迹跟踪平均误差在2.5cm以内的时间
        # 步骤1：获取设定的服务关闭时间，计算关闭服务时间后一秒的轨迹跟踪平均误差，判断是否小于2.5cm
        # 步骤2：如果小于2.5cm，计算关闭服务时间后两秒的轨迹跟踪平均误差，依次类推，直到轨迹跟踪平均误差大于2.5cm
        _close_service_time = int(self.close_service_text.text())  # 服务关闭时间
        _aver_trajectory_dis = 0  # 平均轨迹误差
        _anti_interference_endurance_time = 0  # 抗扰续航时间
        _anti_interference_endurance_points = list()  # 参与计算的轨迹点

        _x_points = self.matplotlib_view.ab_line.get_xdata()
        _y_points = self.matplotlib_view.ab_line.get_ydata()
        _point_a = [_x_points[0], _y_points[0]]
        _point_b = [_x_points[1], _y_points[1]]

        a, b, c = calc_baseline_equation(_point_a, _point_b)

        for index, points in enumerate(self.matplotlib_view_points):
            # 保存服务关闭时间后且平均误差小于2.5cm的下一秒轨迹数据
            if int(points[0]) == _close_service_time + _anti_interference_endurance_time + 1:
                if len(points) == 3:
                    _anti_interference_endurance_points.append(transformer_to_utm(*points[-2:]))
                else:
                    _anti_interference_endurance_points.append(transformer_to_utm(*points[-3:-1]))

            # 当前时间大于下一秒的时间时，开始计算符合条件轨迹点的平均误差
            if int(points[0]) > _close_service_time + _anti_interference_endurance_time + 1 \
                    or index == len(self.matplotlib_view_points) - 1:
                _aver_points = list()
                # 判断当前轨迹点是否大于49个，若不大于则全数参与计算
                if len(_anti_interference_endurance_points) <= global_config["aver_count"]:
                    _aver_points = _anti_interference_endurance_points
                else:
                    # 按照平分轨迹的方式将轨迹50等分
                    _obj = GetLocalizationPoints([_point_a, _point_b], 0, None, aver_nums=global_config["aver_count"])
                    _aver_points = _obj.get_aver_point("ave_trajectory", _anti_interference_endurance_points,
                                                       list(), a, b, c, True)
                _dis_list = [get_distance_of_point_to_line(point, a, b, c) for point in _aver_points]
                if statistics.mean(_dis_list) >= 2.5:
                    break
                else:
                    _anti_interference_endurance_time += 1
        QMessageBox.information(self, "", f"抗扰续航时间为: {_anti_interference_endurance_time} 秒")
